package cs294s.liveradar.service;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import cs294s.liveradar.R;
import cs294s.liveradar.data.Blip;
import cs294s.liveradar.data.Filter;
import edu.stanford.concierge.Concierge;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.database.DataSetObserver;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

/*
 * Communicates with the server. Retrieves filters and sends filters.
 */
public class FilterManager extends Observed{
	
	private static final String FILENAME = "saved_filters";

    /**
     * Holds the single instance that is shared by the process.
     */
    private static FilterManager sInstance;
    private Context mContext;
    
    private Builder alertBox;
    String username;
    String password;

    
	ArrayList<Filter> filters = new ArrayList<Filter>();

	Set<String> ids_added = new HashSet<String>();
	/**
	 * Used to post results back to the UI thread
	 */
	private Handler mHandler = new Handler();

	/**
	 * True if we are in the process of loading
	 */
	private boolean mLoading;



    private FeedManager feedManager;
	
	
    public static FilterManager getInstance(Context c) {
        if (sInstance == null) {
            sInstance = new FilterManager(c);
        }
        return sInstance;
    }
    

    private FilterManager(Context c) {
        mContext = c;
        if(feedManager == null)
        feedManager = FeedManager.getInstance(c);
        filters = new ArrayList<Filter>();
        readFromDisk();
		alertBox = new AlertDialog.Builder(mContext)
		.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {

			}
		});
    }
    
	public void readPreferences() {
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
		username = prefs.getString("ConciergeUsername", "");
		password = prefs.getString("ConciergePassword", "");
	}
    

	/* Check if logged into Concierge */
	public boolean isLoggedIn() {
		return false;
	}

	/*If username and password have changed, then re-login.*/
	public boolean checkLogin() {
		if(isLoggedIn() == false) {
			return loginToServer();
		}
		String prev_username = username;
		String prev_password = password;
		readPreferences();
		if(!prev_username.equals(username) || !prev_password.equals(password))
			return loginToServer();
		return true;
	}

	public void logoutOfServer() {
		//concierge = null;
	}

	public boolean loginToServer() {
		if(!Util.isNetworkAvailable(mContext)) {

			Toast.makeText(mContext, "Cannot connect to filter server. Please check internet connectivity", Toast.LENGTH_SHORT).show();
			//showAlert("Cannot connect to Concierge. Please check internet connectivity");
			return false;
		}

		readPreferences();
		if(username.equals("")) {
			//showAlert("Welcome to LiveRadar. Please go to Settings and enter your Concierge username and password.");
			return false;
		} 
		
		/*
		Toast.makeText(mContext, "Connecting to Concierge...", Toast.LENGTH_SHORT).show();
		
		try {	
			//Toast.makeText(mContext, "Connecting to Concierge...", Toast.LENGTH_SHORT).show();

			concierge = new Concierge("http://colby.stanford.edu/community_vibe/concierge/rpc.php", username, password);
			Toast.makeText(mContext, "Connected to Concierge", Toast.LENGTH_SHORT).show();
			
			//showAlert("Logged in to concierge");
		} catch (Exception e) {
			Toast.makeText(mContext, "Unable to connect to Concierge", Toast.LENGTH_SHORT).show();
			//showAlert("Unable to login to Concierge with username: " + username);

			return false;
		}*/
		return true;
	}

	private void showAlert(String msg) {
		alertBox.setTitle("Concierge Login");
		alertBox.setMessage(msg);
		alertBox.show();
	}


	public boolean sendFilter(Filter filter) {
		if(checkLogin()) {
			/*
			blip.addTag(LIVERADAR_TAG);
			concierge.postMessage(blip.toJSON(), blip.tagsToStringArr());
			return true;
			*/
		}
		return false;
	}


	public int size() {
		return filters.size();
	}

	public Filter get(int position) {
		return filters.get(position);
	}

	/**
	 * Clear all downloaded content
	 */
	public void clear() {
		filters.clear();   
		ids_added.clear();
		notifyObservers();
	}


	/**
	 * Add an item to and notify observers of the change.
	 * @param item The item to add
	 */
	public void add(Filter f) {

		String filter_id = f.getId();
		if(!ids_added.contains(filter_id)){
			ids_added.add(filter_id);
			Log.d("RADAR", "ADDED FILTER: " + filter_id + " TOTAL SIZE: " + size());
			filters.add(f);
			feedManager.addFeed(new Feed(f));
		} else {
			replaceFilter(f);
			feedManager.replaceFeed(new Feed(f));
		}
		saveToDisk();
	}
	
	public void replaceFilter(Filter f) {
		Log.d("RADAR", "REPLACING FILTER");
		for(int i = 0; i < filters.size(); i++) {
			Filter curr = filters.get(i);
			if(curr.getId().equals(f.getId())) {
				filters.set(i, f);
				Log.d("RADAR", "FILTER REPLACED");
				return;
			}
		}
		
	}
	
	private void saveToDisk() {
		String content = "";
		
		for(Filter f : filters) {
			content += f.toJSON().toString() + "\n";
		}
		
		content = content.trim();
		Log.d("RADAR", "WRITTEN TO FILE: " + content);
		
		FileOutputStream fos;
		try {
			fos = mContext.openFileOutput(FILENAME, Context.MODE_PRIVATE);

			fos.write(content.getBytes());
			fos.close();
		
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void readFromDisk() {
		
		clear();
		feedManager.clear();
		try {
			
		FileInputStream fIn = mContext.openFileInput(FILENAME);
	    DataInputStream in = new DataInputStream(fIn);
	    BufferedReader br = new BufferedReader(new InputStreamReader(in));

		    while(true) {
			    String line = br.readLine();
			    if(line == null) break;
			    JSONObject filter_json = (JSONObject) JSONValue.parse(line);
			    Log.d("RADAR", "READ JSON OBJECT: " + filter_json.toString());
			    Filter f = new Filter(filter_json);
			    if(f == null) break;
			    add(f);
			    Log.d("RADAR", "ADDED FILTER FROM DISK: " + f.toJSON().toString());
		    }
		    
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void downloadFilters() {
		if(checkLogin()) {
			mLoading = true;
			new NetworkThread().start();
		}
	}

	/**
	 * This thread does the actual work of downloading and parsing data.
	 *
	 */
	private class NetworkThread extends Thread {
		public NetworkThread() {

		}

		@Override
		public void run() {
			downloadFilters();
		}

		public void downloadFilters() {
			/*
			String[] liveradar_tag_arr = new String[1];
			liveradar_tag_arr[0] = LIVERADAR_TAG;
			JSONArray ja = Concierge.getTaglistStream("http://colby.stanford.edu/community_vibe/concierge/rpc.php", liveradar_tag_arr,  Long.toString(latest_message_id), "10");

			for(int i =ja.size() - 1; i >= 0; i--) {
				try{
					JSONObject j = (JSONObject) ja.get(i);
					long mid = (Long)j.get("mid");
					String content = (String)j.get("content");
					JSONObject blip_json = (JSONObject) JSONValue.parse(content);
					final Blip b = new Blip(blip_json);
					b.setId(mid);
					final boolean done = i == 0;
					mHandler.post(new Runnable() {
						public void run() {
							sInstance.mLoading = !done;
							sInstance.add(b);
						}
					});

				} catch (NullPointerException e) {
					Log.d("RADAR", "CAN'T READ CONCIERGE OBJECT: " + ja.toString());
				}
			}				
			mHandler.post(new Runnable() {
				public void run() {
					sInstance.notifyObservers();
				}
			});
			*/

		}

	}



    
}
